package com.matt.controller.web;

import com.dotflat.util.excelUtil.ExcelUtil;
import com.matt.commons.dto.sso.AreaDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.model.ErrorCode;
import com.matt.commons.model.StatusResponse;
import com.matt.domain.Children;
import com.matt.domain.record.CheckRecord;
import com.matt.foundation.DO.course.CheckRecordDO;
import com.matt.foundation.constant.ChildrenConstant;
import com.matt.foundation.ext.aliyun.OSSProcessService;
import com.matt.foundation.model.MemVerificationCache;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.vo.*;
import com.matt.foundation.vo.course.WebCourseTopicClassesVo;
import com.matt.service.ChildrenService;
import com.matt.service.CourseTopicService;
import com.matt.service.remoteCall.DTO.AreaListDTO;
import com.matt.service.remoteCall.SsoCallService;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileOutputStream;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.commons.model.ErrorCode.DATE_FORMAT_ERROR;
import static com.matt.foundation.constant.RequestConstant.TICKET;

;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2017/7/21
 * *******************************
 */
@RestController
@RequestMapping("/web/home")
public class WebHomeController {

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    private MemVerificationCache cache;

    @Autowired
    private CourseTopicService courseTopicService;

//    @Autowired
//    private NoticeMessageService noticeMessageService;

    @Autowired
    private SsoCallService ssoCallService;

    @Autowired
    private OSSProcessService ossProcessService;

    @Value("${aliyun.oss.fileServerPrefix}")
    private String IMG_SERVICE_PREFIX;

    @ApiOperation(value = "WEB 获取宝宝签到信息,查询全园",httpMethod = "POST")
    @RequestMapping(value = "/check_record", method = RequestMethod.POST)
    public StatusResponse checkRecord(@RequestHeader(TICKET) String ticket) {
       // List<ClassesCheckRecordVo> recordList = childrenService.findClassesCheckRecordByAreaId(cache.getStaffId(ticket));//
        List<ClassesCheckRecordVo> recordList = childrenService.findClassesCheckRecordByAreaId(cache.getAreaId(ticket));
        return StatusResponse.success(recordList);
    }

    @ApiOperation(value = "WEB 获取宝宝签到信息,查询班级",httpMethod = "POST")
    @RequestMapping(value = "/check_record_by_classId", method = RequestMethod.POST)
    public StatusResponse checkRecord(@RequestHeader(TICKET) String ticket,String classId) {
        List<ClassesCheckRecordVo> recordList = childrenService.findClassesCheckRecordByClassId(classId);
        return StatusResponse.success(recordList);
    }

    @ApiOperation(value = "WEB 获取宝宝最后一条签到信息",httpMethod = "POST")
    @RequestMapping(value = "/check_detail_by_childrenId", method = RequestMethod.POST)
    public StatusResponse checkRecordDetail(@RequestHeader(TICKET) String ticket,String childrenId) {
        Date today = new Date();
        CheckRecord record = childrenService.getLastCheckRecord(childrenId);

        if(record == null){
            return StatusResponse.success( new CheckRecordDO());
//            return StatusResponse.error(ErrorCode.CHECK_IN_RECORD_NON, "当前宝宝没有签到记录");
        }

        String childId = record.getChildrenId();
        Children children = childrenService.getById(childId);

        CheckRecordDO returnDo = new CheckRecordDO();
        returnDo.setCheckInTime(record.getCheckInTime());
        returnDo.setCheckOutTime(record.getCheckOutTime());
        returnDo.setHeader(record.getHeader());
        returnDo.setHeight(record.getHeight());
        returnDo.setWeight(record.getWeight());
        returnDo.setHealthStatus(record.getHealthyStatus());
        returnDo.setExceptionName(record.getExceptionName());
        returnDo.setChildrenName(children.getName());
        String birthday = DateUtil.formatDayToStr(children.getBirthday());
        try {
            Integer monthInterval = DateUtil.betweenMonths(DateUtil.millisToDateTime(today.getTime(), "yyyy-MM-dd"), birthday);//月龄
            returnDo.setMonth(monthInterval);
        } catch (ParseException e) {
            throw new BusinessException(DATE_FORMAT_ERROR, "日期格式错误");
        }

        return StatusResponse.success(returnDo);
    }

    @ApiOperation(value = "api 根据ticket获取",httpMethod = "POST")
    @RequestMapping(value = "/get_id_info", method = RequestMethod.POST)
    @ResponseBody
    public StatusResponse getIdInfo(@RequestHeader(TICKET) String ticket) {
        Map map = new HashMap();
        map.put("id", cache.getStaffId(ticket));
        return StatusResponse.success(map);
    }

    @ApiOperation(value = "获取主题课程",httpMethod = "POST")
    @RequestMapping(value = "/topic_by_month", method = RequestMethod.POST)
    @ResponseBody
    public StatusResponse getMonthTopic(String areaId) {
        List<WebCourseTopicClassesVo> topicClassesList = courseTopicService.topicByMonth(areaId);
        return StatusResponse.success(topicClassesList);
    }

//    @ApiOperation(value = "获取提示消息",httpMethod = "POST")
//    @RequestMapping(value = "/notice_message", method = RequestMethod.POST)
//    @ResponseBody
//    public StatusResponse getNoticeMassage(@RequestHeader(TICKET) String ticket, String areaId) {
//        StaffDTO staff = cache.getStaff(ticket);
//        List<NoticeMessageVo> noticeList = noticeMessageService.getNoticeList(staff.getId(), areaId);
//        return StatusResponse.success(noticeList);
//    }
//
//    @ApiOperation(value = "获取历史消息数量",httpMethod = "POST")
//    @RequestMapping(value = "/notice_history_count", method = RequestMethod.POST)
//    @ResponseBody
//    public StatusResponse getNoticeMassageCount(@RequestHeader(TICKET) String ticket, String areaId) {
//        NoticeQuery query = new NoticeQuery();
//
//        StaffDTO staff = cache.getStaff(ticket);
//        query.setStaffId(staff.getId());
//        query.setAreaId(areaId);
//        query.setDueStatus(NoticeMessageConstant.DueStatus.DUE.codeOf());
//        Long count = noticeMessageService.countNoticeMessageHistory(query);
//        return StatusResponse.success(count);
//    }
//
//    @ApiOperation(value = "获取历史消息",httpMethod = "POST")
//    @RequestMapping(value = "/notice_message_history", method = RequestMethod.POST)
//    @ResponseBody
//    public StatusResponse getNoticeMassageHistory(@RequestHeader(TICKET) String ticket, NoticeQuery query) {
//        StaffDTO staff = cache.getStaff(ticket);
//        query.setStaffId(staff.getId());
//        query.setDueStatus(NoticeMessageConstant.DueStatus.DUE.codeOf());
//        Page<NoticeMessageVo> noticeList = noticeMessageService.getNoticeMessageHistory(query);
//        return StatusResponse.success(noticeList);
//    }

    @ApiOperation(value = "获取所负责园区",httpMethod = "POST")
    @RequestMapping(value = "/in_charge_area", method = RequestMethod.POST)
    public StatusResponse inChargeArea(@RequestHeader(TICKET) String ticket) {
        List<AreaListDTO> areaList = ssoCallService.getInChargeArea(ticket);
        return StatusResponse.success(areaList);
    }

    @ApiOperation(value = "修改园区",httpMethod = "POST")
    @RequestMapping(value = "/change_area", method = RequestMethod.POST)
    public StatusResponse changeArea(@RequestHeader(TICKET) String ticket, String areaId) {
        AreaDTO result = ssoCallService.setDefaultArea(ticket, areaId);
        return StatusResponse.success(result);
    }
    
    @ApiOperation(value = "根据宝宝ID和月份获取宝宝的月考勤记录",httpMethod = "POST")
    @RequestMapping(value = "/check_record_by_childrenId", method = RequestMethod.POST)
    public StatusResponse checkRecordByMonth(String childrenId,String month) {
         //childrenId="2c92848c67a0c0dc0167ab87e2f473f2";
         //month="2019-01-01";
    	ChildrenMonthCheckRecordVo recordList = childrenService.findByClassesByChildrenIdAndMonth(childrenId, month);
        return StatusResponse.success(recordList);
    }

    @ApiOperation(value = "根据宝宝ID和月份获取宝宝的月考勤记录",httpMethod = "POST")
    @RequestMapping(value = "/export_excel_check_record", method = RequestMethod.POST)
    public StatusResponse exportExcelCheckRecord(String childrenId,String month) {


        ChildrenMonthCheckRecordVo vo = childrenService.findByClassesByChildrenIdAndMonth(childrenId, month);

        //去重同一天的数据
        List<CheckRecordVo> checkRecordList =  vo.getChildrenCheckRecordList().stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(v -> new DateTime(v.getCreated()).toString("yyyy-MM-dd")))), ArrayList::new)
        );

        vo.setChildrenCheckRecordList(checkRecordList);

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("月考勤");
        final int cellNum = 7;

        createRowIndex0(workbook,sheet,vo);
        createRowIndex1(workbook,sheet,vo,cellNum);
        createRowIndexMonths(workbook,sheet,vo,month,cellNum);
        createRowIndexLast(workbook,sheet,vo,cellNum);
        mergedCell(workbook,sheet,vo);

        sheet.setDefaultColumnWidth(17);
        sheet.setDefaultRowHeight((short) (2 * 256));
        sheet.setHorizontallyCenter(true);
        sheet.setVerticallyCenter(true);

        String uploadedResult = null;
        try{

            String uploadCourseName = vo.getChildrenName() + "(" + month+ ")";
            String fileName = UUID.randomUUID().toString();
            String uploadPath = "teach/file/children_export_excel/" + DateTime.now().toString("yyyy-MM") + "/" + uploadCourseName + ".xls";

            File outputFile = File.createTempFile(fileName,"xls");
            FileOutputStream fileOutputStream = new FileOutputStream(outputFile);

            workbook.write(fileOutputStream);
            String relativePath = ossProcessService.aliyunOssUpload(uploadPath, outputFile);
            uploadedResult = IMG_SERVICE_PREFIX + relativePath;
            outputFile.deleteOnExit();
            fileOutputStream.close();

        }catch (Exception e){
            e.printStackTrace();
        }

        return StatusResponse.success(uploadedResult);
    }


    private static void createRowIndex0(HSSFWorkbook workbook, HSSFSheet sheet , ChildrenMonthCheckRecordVo vo){
        HSSFRow row0 = sheet.createRow(0);
        HSSFCell row0Cell0 = row0.createCell(0);
        row0Cell0.setCellValue(vo.getChildrenName() + "月考勤表");

        HSSFCellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.SEA_GREEN.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.SEA_GREEN.getIndex());

        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);

        row0Cell0.setCellStyle(style);
    }

    private static void createRowIndex1(HSSFWorkbook workbook,HSSFSheet sheet ,ChildrenMonthCheckRecordVo vo,int cellNum){
        HSSFRow row1 = sheet.createRow(1);
        HSSFCellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);

        for (int i = 0 ; i < cellNum; i++){
            row1.createCell(i).setCellStyle(style);
        }

        row1.getCell(0).setCellValue("班级:" + vo.getClassesName());
        row1.getCell(4).setCellValue("当前月龄:" + vo.getMonth());

    }



    private static void createRowIndexMonths(HSSFWorkbook workbook,HSSFSheet sheet ,ChildrenMonthCheckRecordVo vo,String month,int cellNum){

        DateTime date = new DateTime(month);
        int totalDaysOfMonth = date.dayOfMonth().getMaximumValue();
        int totalRow = ((totalDaysOfMonth  +  cellNum  - 1) / cellNum);

        for (int i = 0; i < totalRow; i++){

            HSSFRow rowi,rowiNext;
            boolean isFirstRow = i == 0;

            if(isFirstRow){
                rowi = sheet.createRow(1 + (i + 1));
                rowiNext = sheet.createRow(1 + (i + 1) + 1);
            }else{
                rowi = sheet.createRow(sheet.getLastRowNum() + 1);
                rowiNext = sheet.createRow(rowi.getRowNum() + 1);
            }

            for(int j = 0 ; j < cellNum; j++){
                int cellValueNum = isFirstRow ? (j + 1) : (i * cellNum) + (j + 1);
                String cellValue = cellValueNum > totalDaysOfMonth ? "" : String.valueOf(cellValueNum);
                long hasCheckDay = vo.getChildrenCheckRecordList().stream()
                        .map(v-> new DateTime(v.getCreated()).getDayOfMonth())
                        .filter(d -> String.valueOf(d).equals(cellValue))
                        .count();

                HSSFCell rowiCellJ = rowi.createCell(j);
                HSSFCell rowiNextCellJ = rowiNext.createCell(j);

                rowiCellJ.setCellValue(cellValue);
                if(hasCheckDay > 0)
                    rowiNextCellJ.setCellValue("√");
                else
                    rowiNextCellJ.setCellValue("");

                HSSFCellStyle style = workbook.createCellStyle();
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);

                style.setBorderBottom(BorderStyle.THIN);
                style.setBorderLeft(BorderStyle.THIN);
                style.setBorderRight(BorderStyle.THIN);
                style.setBorderTop(BorderStyle.THIN);

                rowiCellJ.setCellStyle(style);
                rowiNextCellJ.setCellStyle(style);

            }
        }
    }

    public static void createRowIndexLast(HSSFWorkbook workbook,HSSFSheet sheet ,ChildrenMonthCheckRecordVo vo,int cellNum){
        HSSFRow lastRow = sheet.createRow(sheet.getLastRowNum() + 1);
        HSSFCellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        style.setBorderTop(BorderStyle.THIN);

        //这里需要预设cellNum个单元格,如果不预设后续合并两个单元格会覆盖
        for (int i = 0 ; i < cellNum; i++){
            lastRow.createCell(i).setCellStyle(style);
        }

        int totalCheckDays = vo.getChildrenCheckRecordList().size();
        lastRow.getCell(0).setCellValue("总出勤天数:");
        lastRow.getCell(5).setCellValue(totalCheckDays);
    }

    public static void mergedCell(HSSFWorkbook workbook,HSSFSheet sheet,ChildrenMonthCheckRecordVo vo){

        short row2LastCellNum = sheet.getRow(2).getLastCellNum();

        int lastRowNum = sheet.getLastRowNum();

        sheet.addMergedRegion(new CellRangeAddress(0,0,0,row2LastCellNum - 1));

        sheet.addMergedRegion(new CellRangeAddress(1,1,0,3));
        sheet.addMergedRegion(new CellRangeAddress(1,1,4,row2LastCellNum - 1));

        sheet.addMergedRegion(new CellRangeAddress(lastRowNum,lastRowNum,0,4));
        sheet.addMergedRegion(new CellRangeAddress(lastRowNum,lastRowNum,5,row2LastCellNum - 1));

    }


    @ApiOperation(value = "导出 - 班级签到记录",httpMethod = "POST")
    @RequestMapping(value = "/export_check_record_by_classId", method = RequestMethod.POST)
    public StatusResponse exportCheckRecordByClassId(@RequestHeader(TICKET) String ticket,String classId) {
        List<ClassesCheckRecordVo> recordList = childrenService.findClassesCheckRecordByClassId(classId);
        if (recordList.get(0).getChildrenList().size() == 0) {
              return StatusResponse.error(ErrorCode.UNDEFINED, "记录为空");
        }
        List<ChildrenCheckRecordExcelVo>  vo  = recordList.get(0).getChildrenList().stream().map(o->{
            ChildrenCheckRecordExcelVo excelVo = new ChildrenCheckRecordExcelVo();
            //出缺勤状态
            Date today = new Date();
            String todayStr = DateUtil.formatDayToStr(today);
            int checkStatus = o.getCheckStatus()==null?0:o.getCheckStatus(); //0 -"未签到" 1-"入园" 2-"离园" 3-"拒绝入园" 4-"请假"
            if(o.getCheckTime() != null){
                String checkDate = DateUtil.formatDayToStr(o.getCheckTime());
                if(!checkDate.equals(todayStr) && checkStatus != ChildrenConstant.CheckStatus.LEAVE.codeOf() && checkStatus != ChildrenConstant.CheckStatus.REJECTED.codeOf()){
                    excelVo.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.valueOf());
                }else {
                    excelVo.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.valueOf());
                }
            }else{
                excelVo.setCheckStatus(ChildrenConstant.CheckStatus.ABSENT.valueOf());
            }

            excelVo.setChildrenName(o.getChildrenName());
            excelVo.setMonth(o.getMonth());
            excelVo.setHealthyStatus(o.getHealthyStatus() == 0 ? "健康" : "不健康" );
            return excelVo;
        }).collect(Collectors.toList());
        ExcelUtil<ChildrenCheckRecordExcelVo> util = new ExcelUtil<ChildrenCheckRecordExcelVo>(ChildrenCheckRecordExcelVo.class);
        String fileUrl  = util.exportExcel(vo, "学生签到记录");
        String tempPath = "";
        if(File.separatorChar == '/'){
            tempPath =  "/tmp/check_sheet";
        }else {
            tempPath =  "d:";
        }
        File outputFile = new File(tempPath+"/"+fileUrl);
        String uploadPath = "teach/file/children_export_excel/" + DateTime.now().toString("yyyy-MM") + "/" + fileUrl;
        String relativePath = ossProcessService.aliyunOssUpload(uploadPath, outputFile);
        String uploadedResult = IMG_SERVICE_PREFIX + relativePath;
        outputFile.deleteOnExit();
        outputFile.delete();
        return StatusResponse.success(uploadedResult);
    }

}
